struct wl_buffer *
_gdk_wayland_cursor_get_buffer (GdkCursor *cursor,
+ guint image_index,
int *x,
int *y,
int *w,
if (wayland_cursor->wl_cursor)
{
- *x = wayland_cursor->wl_cursor->images[0]->hotspot_x;
- *y = wayland_cursor->wl_cursor->images[0]->hotspot_y;
+ struct wl_cursor_image *image;
- *w = wayland_cursor->wl_cursor->images[0]->width;
- *h = wayland_cursor->wl_cursor->images[0]->height;
+ if (image_index >= wayland_cursor->wl_cursor->image_count)
+ {
+ g_warning (G_STRLOC " out of bounds cursor image [%d / %d]",
+ image_index,
+ wayland_cursor->wl_cursor->image_count - 1);
+ image_index = 0;
+ }
- return wl_cursor_image_get_buffer(wayland_cursor->wl_cursor->images[0]);
+ image = wayland_cursor->wl_cursor->images[image_index];
+
+ *x = image->hotspot_x;
+ *y = image->hotspot_y;
+
+ *w = image->width;
+ *h = image->height;
+
+ return wl_cursor_image_get_buffer (image);
}
else /* From pixbuf */
{
}
}
+guint
+_gdk_wayland_cursor_get_next_image_index (GdkCursor *cursor,
+ guint current_image_index,
+ guint *next_image_delay)
+{
+ struct wl_cursor *wl_cursor = GDK_WAYLAND_CURSOR (cursor)->wl_cursor;
+
+ if (wl_cursor && wl_cursor->image_count > 1)
+ {
+ if (current_image_index >= wl_cursor->image_count)
+ {
+ g_warning (G_STRLOC " out of bounds cursor image [%d / %d]",
+ current_image_index, wl_cursor->image_count - 1);
+ current_image_index = 0;
+ }
+
+ /* Return the time to next image */
+ if (next_image_delay)
+ *next_image_delay = wl_cursor->images[current_image_index]->delay;
+
+ return (current_image_index + 1) % wl_cursor->image_count;
+ }
+ else
+ return current_image_index;
+}
+
static void
_gdk_wayland_cursor_class_init (GdkWaylandCursorClass *wayland_cursor_class)
{
if (!set_cursor_from_theme (private, wayland_display->cursor_theme))
return GDK_CURSOR (private);
- /* TODO: Do something clever so we can do animated cursors - move the
- * wl_pointer_set_cursor to a function here so that we can do the magic to
- * iterate through
- */
-
add_to_cache (wayland_display, private);
return GDK_CURSOR (private);
guint32 repeat_count;
GSettings *keyboard_settings;
+ guint cursor_timeout_id;
+ guint cursor_image_index;
+
DataOffer *drag_offer;
DataOffer *selection_offer;
}
}
+static void
+gdk_wayland_device_stop_window_cursor_animation (GdkWaylandDeviceData *wd)
+{
+ if (wd->cursor_timeout_id > 0)
+ {
+ g_source_remove (wd->cursor_timeout_id);
+ wd->cursor_timeout_id = 0;
+ }
+ wd->cursor_image_index = 0;
+}
+
+static gboolean
+gdk_wayland_device_update_window_cursor (GdkWaylandDeviceData *wd)
+{
+ struct wl_buffer *buffer;
+ int x, y, w, h;
+ guint next_image_index, next_image_delay;
+
+ buffer = _gdk_wayland_cursor_get_buffer (wd->cursor, wd->cursor_image_index,
+ &x, &y, &w, &h);
+ wl_pointer_set_cursor (wd->wl_pointer,
+ wd->enter_serial,
+ wd->pointer_surface,
+ x, y);
+ wl_surface_attach (wd->pointer_surface, buffer, 0, 0);
+ wl_surface_damage (wd->pointer_surface, 0, 0, w, h);
+ wl_surface_commit (wd->pointer_surface);
+
+ next_image_index =
+ _gdk_wayland_cursor_get_next_image_index (wd->cursor,
+ wd->cursor_image_index,
+ &next_image_delay);
+
+ if (next_image_index != wd->cursor_image_index)
+ {
+ guint id;
+
+ /* Queue timeout for next frame */
+ id = g_timeout_add (next_image_delay,
+ (GSourceFunc)gdk_wayland_device_update_window_cursor,
+ wd);
+
+ wd->cursor_timeout_id = id;
+ wd->cursor_image_index = next_image_index;
+ }
+ else
+ wd->cursor_timeout_id = 0;
+
+ return FALSE;
+}
+
static void
gdk_wayland_device_set_window_cursor (GdkDevice *device,
GdkWindow *window,
GdkCursor *cursor)
{
GdkWaylandDeviceData *wd = GDK_WAYLAND_DEVICE(device)->device;
- struct wl_buffer *buffer;
- int x, y, w, h;
/* Setting the cursor to NULL means that we should use the default cursor */
if (!cursor)
if (cursor == wd->cursor)
return;
+ gdk_wayland_device_stop_window_cursor_animation (wd);
+
if (wd->cursor)
g_object_unref (wd->cursor);
wd->cursor = g_object_ref (cursor);
- buffer = _gdk_wayland_cursor_get_buffer (wd->cursor, &x, &y, &w, &h);
- wl_pointer_set_cursor (wd->wl_pointer,
- wd->enter_serial,
- wd->pointer_surface,
- x, y);
- wl_surface_attach (wd->pointer_surface, buffer, 0, 0);
- wl_surface_damage (wd->pointer_surface, 0, 0, w, h);
- wl_surface_commit (wd->pointer_surface);
+ gdk_wayland_device_update_window_cursor (wd);
}
static void
g_object_unref(device->pointer_focus);
if (device->cursor)
{
+ gdk_wayland_device_stop_window_cursor_animation (device);
g_object_unref (device->cursor);
device->cursor = NULL;
}